package com.fei.wechat.admin.aspect;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.fei.wechat.admin.aspect.annotation.AnnoOperateLog;
import com.fei.wechat.common.constant.Constants;
import com.fei.wechat.common.model.vo.RespVo;
import com.fei.wechat.middlewar.api.admin.IOperateLogService;
import com.fei.wechat.middlewar.mode.vo.admin.CurrentUser;

/**
 * 描述: 日志aop处理
 * 版权: Copyright (c) 2018 
 * 公司: 飞翔科技 
 * 作者: 张进飞 
 * 版本: 1.0 
 * 创建日期: 2018年4月22日 
 * 创建时间: 下午9:09:58
 */
@Aspect
@Component("operateLogAspect")
public class OperateLogAspect
{
    
    /*
     * 日志
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(OperateLogAspect.class);
    
    @Autowired
    private IOperateLogService operateLogService;
    
    /**
     * 操作日志切入点
     */
    @Pointcut("@annotation(com.fei.wechat.admin.aspect.annotation.AnnoOperateLog)")
    public void operateLogAspect()
    {
        
    }
    
    /**
     * 描述：方法运行完后返回时执行-操作日志记录
     * 作者：张进飞
     * 时间：2018年4月22日 下午10:32:57
     * @param joinPoint
     * @param returnVo
     */
    @AfterReturning(returning = "returnVo", pointcut = "operateLogAspect()")
    public void doOperateLog(JoinPoint joinPoint, Object returnVo)
    {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        CurrentUser user = (CurrentUser) request.getSession().getAttribute(Constants.USER_LOGIN_FLAG);
        if (null == user)
        {
            return;
        }
        //登录名
        String loginName = user.getUser().getLoginName();
        //获取IP
        String operateIP = getLoginIP(request);
        
        RespVo respVo = (RespVo) returnVo;
        //操作日志，参数列表
        Object[] logArgas = respVo.getLogArgs();
        String operateContent = respVo.getLogMsg();
        operateContent = StringUtils.isEmpty(operateContent) ? respVo.getMessage() : operateContent;
        try
        {
            AnnoOperateLog anno = this.getMthodAnno(joinPoint, AnnoOperateLog.class);
            if (null == anno)
            {
                return;
            }
            String moduleName = anno.moduleName();
            String function = anno.function();
            int operateType = anno.operateType();
            String operateContentTemplate = anno.operateContentTemplate();
            operateLogService.saveOperateLog(moduleName, function, loginName, operateIP, operateType, operateContentTemplate, logArgas);
        }
        catch (Exception e)
        {
            // 记录本地异常日志  
            LOGGER.error("记录操作日志异常");
            LOGGER.error("异常信息:{}", e);
        }
    }
    
    /**
     * 描述：获取注解
     * 作者：张进飞
     * 时间：2018年4月22日 下午10:30:29
     * @param joinPoint
     * @param t
     * @return
     * @throws Exception
     */
    private <T extends Annotation> T getMthodAnno(JoinPoint joinPoint, Class<T> t) throws Exception
    {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class<?> targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        T rt = null;
        for (Method method : methods)
        {
            if (method.getName().equals(methodName))
            {
                Class<?>[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length)
                {
                    rt = method.getAnnotation((Class<T>) t);
                    break;
                }
            }
        }
        return rt;
    }
    
    /**
     * 描述：获取登录IP
     * 作者：张进飞
     * 时间：2018年4月22日 下午10:33:16
     * @param request
     * @return
     */
    public String getLoginIP(HttpServletRequest request)
    {
        String ip = request.getHeader("x-forwarded-for");
        if (!checkIP(ip))
        {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (!checkIP(ip))
        {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (!checkIP(ip))
        {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
    
    /**
     * 描述：检查IP
     * 作者：张进飞
     * 时间：2018年4月22日 下午10:33:34
     * @param ip
     * @return
     */
    private boolean checkIP(String ip)
    {
        if (ip == null || ip.length() == 0 || "unkown".equalsIgnoreCase(ip) || ip.split(".").length != 4)
        {
            return false;
        }
        return true;
    }
    
}
